package com.gitee.wsl.mathematics.matrix.mat3

import com.gitee.wsl.mathematics.matrix.M
import com.gitee.wsl.mathematics.matrix.MatCopyInitializer
import com.gitee.wsl.mathematics.matrix.MatrixD
import com.gitee.wsl.mathematics.matrix.MatrixF
import com.gitee.wsl.mathematics.matrix.MutableMatrix
import com.gitee.wsl.mathematics.matrix.N
import com.gitee.wsl.mathematics.matrix.mat2.MutableMatrix2
import com.gitee.wsl.mathematics.vector.vec3.MutableVector3
import com.gitee.wsl.mathematics.vector.vec3.Vector3

interface MutableMatrix3<T:Number,V: Matrix3<T, V, R>,R: Vector3<T, R>>: Matrix3<T, V, R>,MutableMatrix<T,V,R>{

    override val m: List<MutableVector3<T, R>>

    override val n: List<MutableVector3<T, R>>

    override var m00: T get() = proxy[0] ;set(value) { proxy[0] = value }
    override var m01: T get() = proxy[1] ;set(value) { proxy[1] = value }
    override var m02: T get() = proxy[2] ;set(value) { proxy[2] = value }
    override var m10: T get() = proxy[3] ;set(value) { proxy[3] = value }
    override var m11: T get() = proxy[4] ;set(value) { proxy[4] = value }
    override var m12: T get() = proxy[5] ;set(value) { proxy[5] = value }
    override var m20: T get() = proxy[6] ;set(value) { proxy[6] = value }
    override var m21: T get() = proxy[7] ;set(value) { proxy[7] = value }
    override var m22: T get() = proxy[8] ;set(value) { proxy[8] = value }

    //override fun createVec(indexRage: IntRange): MutableVector3<T, R>

    override fun scale(factor: T){
        n[0] *= factor
        n[1] *= factor
    }

    override fun copy(block: MatCopyInitializer<T>): MutableMatrix3<T, V, R>

    override fun copyEmpty() = copy(block ={ _, _ -> zero})

    override fun copyIdentity() = copy(block ={ i, j -> if( i == j) one else zero})

    override fun createVec(indexes: List<Int>): MutableVector3<T, R>

    override fun createMat2(block:(MutableMatrix2<T, *, *>)->Unit): MutableMatrix2<T, *, *>

    override fun toMutable() = this

    override operator fun M.get(row: Int) = createVec(rowIndexes(row))

    override operator fun N.get(col: Int) = createVec(colIndexes(col))

    operator fun set(row: Int,m: Vector3<T, *>) = M.set(row,m)


    override fun copy(
        m00: T?, m01: T?, m02: T?,
        m10: T?, m11: T?, m12: T?,
        m20: T?, m21: T?, m22: T?
    ) = create(
        m00 ?: this.m00,
        m01 ?: this.m01,
        m02 ?: this.m02,
        m10 ?: this.m10,
        m11 ?: this.m11,
        m12 ?: this.m12,
        m20 ?: this.m20,
        m21 ?: this.m21,
        m22 ?: this.m22
    )

    fun set(
        m00: T, m01: T, m02: T,
        m10: T, m11: T, m12: T,
        m20: T, m21: T, m22: T
    ){
        this.m00=m00
        this.m01=m01
        this.m02=m02
        this.m10=m10
        this.m11=m11
        this.m12=m12
        this.m20=m20
        this.m21=m21
        this.m22=m22
    }

    operator fun M.set(row: Int, m: Vector3<T, *>){
        set(row,0,m[0])
        set(row,1,m[1])
        set(row,2,m[2])
    }

    operator fun N.set(colIndex: Int, m: Vector3<T, *>){
        set(0,colIndex,m[0])
        set(1,colIndex,m[1])
        set(2,colIndex,m[2])
    }

/*    override fun timesAssign(other: V) = set(
        m00 * other.m00 + m01 * other.m10 + m02 * other.m20,
        m00 * other.m01 + m01 * other.m11 + m02 * other.m21,
        m00 * other.m02 + m01 * other.m12 + m02 * other.m22,
        m10 * other.m00 + m11 * other.m10 + m12 * other.m20,
        m10 * other.m01 + m11 * other.m11 + m12 * other.m21,
        m10 * other.m02 + m11 * other.m12 + m12 * other.m22,
        m20 * other.m00 + m21 * other.m10 + m22 * other.m20,
        m20 * other.m01 + m21 * other.m11 + m22 * other.m21,
        m20 * other.m02 + m21 * other.m12 + m22 * other.m22
    )*/

}

interface MutableMatrix3F<V: Matrix3<Float, V,  R>,R:Vector3<Float,R>>: MutableMatrix3<Float, V, R>, MatrixF<V, R>

interface MutableMatrix3D<V: Matrix3<Double, V, R>,R:Vector3<Double,R>>: MutableMatrix3<Double, V, R>, MatrixD<V, R>